package com.info.zhiduoduo.core.service.common;

import com.auth0.jwt.interfaces.DecodedJWT;
import com.info.zhiduoduo.common.constants.StatusMsg;
import com.info.zhiduoduo.common.exception.Asserts;
import com.info.zhiduoduo.common.exception.SmartException;
import com.info.zhiduoduo.common.utils.DateUtil;
import com.info.zhiduoduo.core.configs.jwt.JwtUtil;
import com.info.zhiduoduo.core.configs.jwt.UserLocal;
import com.info.zhiduoduo.core.vo.auth.UserAuthVO;

import org.springframework.stereotype.Service;

import java.util.Date;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class JwtService {

	/** token过期时间，30分钟 */
	private static final int EXPIRE_MINUTES = 30;
	/** token刷新时间，5分钟。颁发5分钟后刷新 */
	private static final int REFRESH_MINUTES = 5;

	public String createToken(UserAuthVO vo) {
		Date expireAt = DateUtil.addMinute(new Date(), EXPIRE_MINUTES);
		return JwtUtil.getToken(vo, expireAt);
	}

	/**
	 * 检查当前接口传递的token是否有效。无效则报错，有效则返回同一token或新的token
	 *
	 * @param token 接口请求传递的token
	 * @return 同一token或者刷新后的token
	 */
	public String check(String token) {
		Asserts.notEmpty(token, StatusMsg.StatusMsg_137);

		// 检查token
		DecodedJWT jwt;
		try {
			jwt = JwtUtil.check(token);
		} catch (Exception e) {
			throw SmartException.of(StatusMsg.StatusMsg_138);
		}

		// 获取用户信息, 并放入ThreadLocal供后续使用
		UserAuthVO vo = JwtUtil.parseUser(jwt);
		Asserts.notNull(vo, StatusMsg.StatusMsg_139);
		UserLocal.save(vo);

		// 检查是否超过刷新时间，重新颁发token
		Date issuedAt = jwt.getIssuedAt();
		if (System.currentTimeMillis() - issuedAt.getTime() >= REFRESH_MINUTES * 60 * 1000L) {
			token = createToken(vo);
		}

		return token;
	}

	/**
	 * 清除用户信息，一般在接口调用结束后清空缓存，防止内存泄露
	 */
	public void clearUserLocal() {
		UserLocal.clear();
	}
}
